package com.bbzn.device.client.controller;

import com.alibaba.fastjson.JSONObject;
import com.bbzn.device.client.vo.req.*;
import com.bbzn.device.client.vo.res.DeviceResVO;
import com.bbzn.device.client.aspect.OperationAnnotation;
import com.bbzn.device.client.config.EmqCode;
import com.bbzn.device.client.constant.*;
import com.bbzn.device.client.dataobject.*;
import com.bbzn.device.client.dto.api.ct.request.RequestCreateDevice;
import com.bbzn.device.client.dto.api.ct.request.RequestCreateDeviceParam;
import com.bbzn.device.client.dto.api.ct.response.CreateDeviceResult;
import com.bbzn.device.client.dto.api.ct.response.ResponseBase;
import com.bbzn.device.client.dto.api.ct.response.ResponseCreateDevice;
import com.bbzn.device.client.dto.device.*;
import com.bbzn.device.client.dto.product.ProductExistDTO;
import com.bbzn.device.client.exception.DefinitException;
import com.bbzn.device.client.service.*;
import com.bbzn.device.client.utils.*;
import com.bbzn.device.client.utils.date.DateUtil;
import com.bbzn.iotcard.client.IotcardOrderClient;
import com.bbzn.iotcard.comment.api.client.com.ClientResult;
import com.bbzn.iotcard.comment.api.client.req.IotProductReq;
import com.bbzn.iotcard.comment.api.client.res.IotProductRes;
import com.bbzn.user.client.TenantClient;
import com.bbzn.user.client.UserClient;
import com.bbzn.user.comment.Tenant;
import com.bbzn.user.comment.User;
import com.bbzn.user.comment.res.TenantRes;
import com.ctg.ag.sdk.biz.aep_device_management.CreateDeviceResponse;
import com.ctg.ag.sdk.biz.aep_device_management.DeleteDeviceResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;

/**
 * @Author 蒋洪媛
 * @Date 2021/11/17 17:11
 * @Version 2.0
 */

@RestController
@RequestMapping("/device")
@Slf4j
//@CrossOrigin
public class DeviceController extends BaseApiService {

    @Autowired
    private CommonService commonService;

    @Autowired
    private SystemParamByCacheService systemParamByCacheService;

    @Autowired
    private UserClient userClient;

    @Autowired
    private TenantClient tenantClient;

    @Autowired
    private IotcardOrderClient iotcardOrderClient;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private DeviceCategoryService deviceCategoryService;

    @Autowired
    private DeviceManagementService deviceManagementService;

    @Autowired
    private RedisUtils<String> redisUtil;

    @Autowired
    private IotCardService iotCardService;

    @Autowired
    private FenceDeviceService fenceDeviceService;

    @Autowired
    private FenceService fenceService;

    @Autowired
    private ProductService productService;

    @Autowired
    private PhotoUploadService photoUploadService;

    @Autowired
    private PublishService publishService;

    @Autowired
    @Qualifier("threadPoolExecutorForVideo")
    private Executor executor;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 三级：获取对应产品的设备列表
     *
     * @param reqVO
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getDeviceList", method = RequestMethod.POST)
    @OperationAnnotation(content = "三级：获取对应产品的设备列表+条件查询")
    public BaseResponse getDeviceList(@RequestBody DeviceVO reqVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getDeviceCategoryId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DESID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        DeviceDTO dto = new DeviceDTO();
        if (OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            dto.setImei(reqVO.getImei());
        }
        if (OptionalBean.ofNullable(reqVO.getImsi()).isPresent()) {
            dto.setImsi(reqVO.getImsi());
        }
        if (null != reqVO.getUsed()) {
            dto.setUsed(reqVO.getUsed());
        }
        if (null != reqVO.getPageNum()) {
            dto.setPageNum(reqVO.getPageNum());
        }
        if (null != reqVO.getPageSize()) {
            dto.setPageSize(reqVO.getPageSize());
        }

        dto.setStartIndex((reqVO.getPageNum() - 1) * reqVO.getPageSize());
        dto.setDeviceCategoryId(reqVO.getDeviceCategoryId());
        dto.setOperatorId(userId);
        dto.setUserId(userId);
        PageInfo<Device> devices = deviceService.findPageByAll(dto);
        return setResultSuccess(devices);
    }

    /**
     * 设备列表
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getProDeviceList", method = RequestMethod.POST)
    @OperationAnnotation(content = "设备列表")
    public BaseResponse getProDeviceList(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        JSONObject data = new JSONObject();
        DeviceDTO dto = new DeviceDTO();
        if (OptionalBean.ofNullable(reqVO.getProductId()).isPresent()) {
            dto.setProductId(reqVO.getProductId());
        } else {
            List<ProductExistDTO> existProducts = productService.findByProducts();
            if (CollectionUtils.isEmpty(existProducts)) {
                systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.SELECT_SUCCESS_PREFIX + language);
                throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
            }
            ProductExistDTO showProduct = existProducts.get(0);
            //dto.setProductId(showProduct.getId());
            data.put("products", existProducts);
        }
        if (!OptionalBean.ofNullable(reqVO.getPageSize()).isPresent()) {
            reqVO.setPageSize(PageConstant.PAGE_SIZE);
        }
        if (!OptionalBean.ofNullable(reqVO.getPageNum()).isPresent()) {
            reqVO.setPageNum(PageConstant.PAGE_NUM);
        }

        if (null != reqVO.getPageNum()) {
            dto.setPageNum(reqVO.getPageNum());
        }
        if (null != reqVO.getPageSize()) {
            dto.setPageSize(reqVO.getPageSize());
        }
        // 模糊查詢
        if (OptionalBean.ofNullable(reqVO.getState()).isPresent()) {
            dto.setState(reqVO.getState());
        }
        if (OptionalBean.ofNullable(reqVO.getName()).isPresent()) {
            dto.setName(reqVO.getName());
        }
        if (OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            dto.setImei(reqVO.getImei());
        }
        if (OptionalBean.ofNullable(reqVO.getUsed()).isPresent()) {
            dto.setUsed(reqVO.getUsed());
        }
        dto.setStartIndex((reqVO.getPageNum() - 1) * reqVO.getPageSize());

        dto.setOperatorId(userId);
        dto.setUserId(userId);
        PageInfo<Device> devices = deviceService.findPageByAll(dto);
        data.put("devices", devices);
        return setResultSuccess(data);
    }


    /**
     * 添加设备
     * 1、超级管理员第一次添加设备时，不做流程记录
     * 2、第一次进行分配时开始记录
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/addDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "添加设备")
    public BaseResponse addDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getProductId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getDeviceCategoryId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVICE_CATEGORY_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getImsi()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMSI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getOperator()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_OPERATOR_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getSysVersion()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_SYS_VER_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getAppVersion()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_APP_VER_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        String userName = MayiktJwtUtils.getUsername(request, secretKey);

        DeviceCategory deviceCategory = deviceCategoryService.selectByPrimaryKey(reqVO.getDeviceCategoryId());

        DeviceDTO query = new DeviceDTO();
        query.setImei(reqVO.getImei());
        int count = deviceService.findCountByAll(query);
        if (count > 0) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_CANT_ANAGIN_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        User user = userClient.selectByPrimaryKey(userId);
        if (null == user.getTenantId() || "".equals(user.getTenantId())) {
            systemParam = systemParamByCacheService.getValues(AuditConstant.AUDIT_ENUM, AuditConstant.AUDIT_NO_COMPANY_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Device device = new Device();
        Tenant tenant = tenantClient.selectByPrimaryKey(user.getTenantId());

        device.setImei(reqVO.getImei());
        device.setIccid(reqVO.getIccid());
        device.setImsi(reqVO.getImsi());
        device.setName(deviceCategory.getName());
        //应产品和测试要求超级列表添加设备时不显示公司，分配后才显示
        device.setCompany(tenant.getTenantName());
        device.setSysVersion(reqVO.getSysVersion());
        device.setAppVersion(reqVO.getAppVersion());
        device.setUserId(userId);
        device.setOperator(reqVO.getOperator());
        device.setSku(reqVO.getSku());
        device.setState(2);
        device.setCreateTime(new Date());
        device.setCreatedBy(userName);
        device.setDeviceCategoryId(reqVO.getDeviceCategoryId());
        device.setUsed(1);
        device.setProductId(reqVO.getProductId());

        CreateNbDeviceDTO createNbDeviceDTO = deviceCategoryService.queryNbParam(reqVO.getDeviceCategoryId());
        if (createNbDeviceDTO == null || StringUtils.isEmpty(createNbDeviceDTO.getMasterKey())) {
            deviceService.insertSelective(device);
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_ADD_SUCCESS_PREFIX + language);
            return setResultSuccess(systemParam.getMassage());
        }
        Integer proType = createNbDeviceDTO.getProType();
        if (proType == null) {
            systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_NB_PRODUCT_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!proType.equals(1)) {
            systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_NB_PRODUCT_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String name = createNbDeviceDTO.getName();
        String masterKey = createNbDeviceDTO.getMasterKey();
        if (!OptionalBean.ofNullable(name).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVNAME_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(masterKey).isPresent()) {
            systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_MASTER_KEY_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        RequestCreateDevice createNb = new RequestCreateDevice();
        createNb.setDeviceName(name);
        createNb.setImei(reqVO.getImei());
        createNb.setOperator(userName);
        createNb.setProductId(createNbDeviceDTO.getNbProductId());

        RequestCreateDeviceParam param = new RequestCreateDeviceParam();
        param.setAutoObserver(0);
        param.setImse(reqVO.getImsi());
        createNb.setOther(param);
        CreateDeviceResponse response = deviceManagementService.createDevice(masterKey, createNb);
        // 4.响应结果
        int code = response.getStatusCode();
        if (code != 200) {
            throw new DefinitException(code, response.getMessage());
        }
        byte[] retBody = response.getBody();
        System.out.println(retBody);
        ResponseCreateDevice responseCreateDevice = JsonUtils.byteToJaveBean(retBody, ResponseCreateDevice.class);
        Integer resCode = responseCreateDevice.getCode();
        if (resCode != 0) {
            throw new DefinitException(resCode, responseCreateDevice.getMsg());
        }
        CreateDeviceResult createProductResult = responseCreateDevice.getResult();

        device.setNbDeviceId(createProductResult.getDeviceId());
        device.setName(createNbDeviceDTO.getName());

        device.setDeviceCategoryId(reqVO.getDeviceCategoryId());
        device.setLocation(reqVO.getLocation());
        deviceService.insertSelective(device);

        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_ADD_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

//    /**
//     * 添加NB设备
//     * 1、超级管理员第一次添加设备时，不做流程记录
//     * 2、第一次进行分配时开始记录
//     *
//     * @param reqVO
//     * @param request
//     * @return
//     * @throws Exception
//     */
//    @RequestMapping(value = "/addNBDevice", method = RequestMethod.POST)
//    @OperationAnnotation(content = "添加NB设备")
//    public BaseResponse addNBDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
//        SystemParam systemParam = null;
//        String secretKey = commonService.getWebSalt(request);
//        String language = MayiktJwtUtils.getLanguage(request, secretKey);
//        Long userId = commonService.getUserId(request);
//        if (!OptionalBean.ofNullable(userId).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getProductId()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_ID_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getDeviceCategoryId()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVICE_CATEGORY_ID_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getImsi()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMSI_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getOperator()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_OPERATOR_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getSysVersion()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_SYS_VER_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        if (!OptionalBean.ofNullable(reqVO.getAppVersion()).isPresent()) {
//            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_APP_VER_PREFIX + language);
//            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
//        }
//        String userName = MayiktJwtUtils.getUsername(request, secretKey);
//        deviceService.addNBDevice(userId, reqVO, userName, language);
//        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_ADD_SUCCESS_PREFIX + language);
//        return setResultSuccess(systemParam.getMassage());
//    }

    /**
     * 更新设备
     * 暂没看到用
     *
     * @param reqVO
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "更新设备")
    public BaseResponse updateDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        if (!OptionalBean.ofNullable(reqVO.getName()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVNAME_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        /*if (!OptionalBean.ofNullable(reqVO.getName()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVNAME_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }*/
        Device device = new Device();
        device.setName(reqVO.getName());
        if (StringUtils.isNotEmpty(reqVO.getSku())) {
            device.setSku(reqVO.getSku());
        }
        if (StringUtils.isNotEmpty(reqVO.getRemark())) {
            device.setRemark(reqVO.getRemark());
        }
        device.setId(reqVO.getId());

        device.setUpdateTime(new Date());
        device.setUpdatedBy(MayiktJwtUtils.getUsername(request, secretKey));
        deviceService.updateByPrimaryKeySelective(device);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_INFO_UPDATE_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 更新sku
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateDeviceSku", method = RequestMethod.POST)
    @OperationAnnotation(content = "更新sku")
    public BaseResponse updateDeviceSku(@RequestBody Device reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (reqVO.getSku().isEmpty()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_UN_SKU_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Device device = new Device();
        device.setImei(reqVO.getImei());
        device.setSku(reqVO.getSku());
        device.setUpdateTime(new Date());
        device.setUpdatedBy(MayiktJwtUtils.getUsername(request, secretKey));
        deviceService.updateByImeiSelective(device);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_UPDATE_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }


    /**
     * 查询sku
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getDeviceSku", method = RequestMethod.POST)
    @OperationAnnotation(content = "查询sku")
    public BaseResponse getDeviceSku(@RequestBody Device reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Device device = new Device();
        device.setImei(reqVO.getImei());
        SkuDTO sku = deviceService.selectSkuByImei(reqVO.getImei());
        return setResultSuccess(sku);
    }


    /**
     * 查询可分配的设备列表
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getBindCompanyList", method = RequestMethod.POST)
    @OperationAnnotation(content = "查询可分配的设备列表")
    public BaseResponse getBindCompanyList(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        DeviceDTO dto = new DeviceDTO();
        if (null != reqVO.getPageNum()) {
            dto.setPageNum(reqVO.getPageNum());
        }
        if (null != reqVO.getPageSize()) {
            dto.setPageSize(reqVO.getPageSize());
        }
        dto.setStartIndex((reqVO.getPageNum() - 1) * reqVO.getPageSize());

        List<Integer> useds = new ArrayList<>();
        useds.add(1);
        useds.add(2);
        useds.add(4);
        useds.add(5);

        dto.setUserId(userId);
        dto.setUseds(useds);
        PageInfo<Device> deviceList = deviceService.selectPageBySelective(dto);
        return setResultSuccess(deviceList);
    }

    /**
     * 查询可分配的公司用户列表
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getTenantUserList", method = RequestMethod.POST)
    @OperationAnnotation(content = "查询可分配的公司用户列表")
    public BaseResponse getTenantUserList(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        List<Long> userIds = commonService.getUserIds(userId);
        int roleId = MayiktJwtUtils.getRoleId(request, secretKey);
        List<TenantRes> tenantRes = new ArrayList<>();
        if (roleId == 1) {
            tenantRes = tenantClient.selectTenantUnUserAll();
        } else {
            /*List<User> userList = userClient.selectBatchIds(userIds);
            userList.remove(0); //去掉自己 - 第一个是自己
            tenantRes.get(0).setUserList(userList);*/
            tenantRes = tenantClient.selectTenantUnUser(userId);
        }
        return setResultSuccess(tenantRes);
    }


    /**
     * 分配设备
     * 1、管理员分配设备，开始记录流程。
     * 2、当前登录的用户是分配人，当前用户选择的用户是接收人
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/bindCompany", method = RequestMethod.POST)
    @OperationAnnotation(content = "分配设备")
    public BaseResponse bindCompany(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        if (!OptionalBean.ofNullable(reqVO.getId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getReceiveId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_RECEIVE_ID_NULL_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        User user = userClient.selectByPrimaryKey(userId);
        if (null == user.getTenantId() || "".equals(user.getTenantId())) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ALLOT_ERROR_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        deviceService.bindCompany(userId, reqVO.getId(), reqVO.getReceiveId(), userName, language);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_OPERATET_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 批量分配设备
     *
     * @param reqVO
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/bingCompanies", method = RequestMethod.POST)
    @OperationAnnotation(content = "批量分配设备")
    public BaseResponse bingCompanies(@RequestBody DeviceVO reqVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        if (!OptionalBean.ofNullable(reqVO.getIds()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getReceiveId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_RECEIVE_ID_NULL_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        deviceService.bingCompanies(userId, reqVO.getIds(), reqVO.getReceiveId(), userName, language);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_OPERATET_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 删除设备 + 删除NB电信平台上的设备
     * 1、报警信息、健康数据、围栏、设备分组、设备信息、分配流程、分享数据
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @Transactional
    @RequestMapping(value = "/delDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "删除设备 + 删除NB电信平台上的设备")
    public BaseResponse delDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Device device = deviceService.selectByPrimaryKey(reqVO.getId());
        if (device == null) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_ID_NOT_EXIST_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String nbId = device.getNbDeviceId();
        // NB设备
        if (StringUtils.isNotEmpty(nbId)) {
            CreateNbDeviceDTO createNbDeviceDTO = deviceCategoryService.queryNbParam(device.getDeviceCategoryId());
            DeleteDeviceResponse response = deviceManagementService.deleteDevice(createNbDeviceDTO.getMasterKey(), createNbDeviceDTO.getNbProductId(), device.getNbDeviceId());
            // 4.响应结果
            int code = response.getStatusCode();
            if (code != 200) {
                throw new DefinitException(code, response.getMessage());
            }
            byte[] retBody = response.getBody();
            System.out.println(retBody);
            ResponseBase base = JsonUtils.byteToJaveBean(retBody, ResponseBase.class);
            Integer resCode = base.getCode();
            if (resCode != 0) {
                throw new DefinitException(resCode, base.getMsg());
            }
        }
        if (null == device.getUsed() || device.getUsed() == 3) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_HAS_BINGS_PREFIX + language);
            User user = userClient.selectByPrimaryKey(device.getUserId());
            if (null != user && StringUtils.isNotEmpty(user.getPhone())) {
                throw new DefinitException(systemParam.getCode(), systemParam.getMassage() + user.getPhone());
            }
            if (language.equals("EN")) {
                throw new DefinitException(systemParam.getCode(), systemParam.getMassage() + "nothing");
            } else {
                throw new DefinitException(systemParam.getCode(), systemParam.getMassage() + "无");
            }
        }
        //删除设备的报警、健康数据、sos、轨迹坐标、设备分组、围栏、分配流程、分享数据
        deviceService.delDeviceByInfoAll(device.getImei());
        //设备
        deviceService.deleteByPrimaryKey(reqVO.getId());
        systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.DELETE_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 回收设备
     * 1、删除报警信息、健康数据、围栏、设备分组、设备信息、分配流程、分享数据
     * 2、变更设备为回收状态
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @Transactional
    @RequestMapping(value = "/recyclingDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "回收设备")
    public BaseResponse recyclingDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getId()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Device device = deviceService.selectByPrimaryKey(reqVO.getId());
        if (device == null) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_ID_NOT_EXIST_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        //删除设备的报警、健康数据、sos、轨迹坐标、设备分组、围栏、分配流程、分享数据
        deviceService.delDeviceByInfoAll(device.getImei());

        User user = userClient.selectByPrimaryKey(userId);
        if (null == user.getTenantId() || "".equals(user.getTenantId())) {
            systemParam = systemParamByCacheService.getValues(AuditConstant.AUDIT_ENUM, AuditConstant.AUDIT_NO_COMPANY_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Tenant tenant = tenantClient.selectByPrimaryKey(user.getTenantId());
        //设备
        device.setUserId(userId);
        device.setUsed(5);
        device.setCompany(tenant.getTenantName());
        device.setUpdatedBy(MayiktJwtUtils.getUsername(request, secretKey));
        device.setUpdateTime(new Date());
        deviceService.updateByPrimaryKeySelective(device);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_OPERATET_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }


    /**
     * 管理员强制解绑设备
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @Transactional
    @RequestMapping(value = "/unbindDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "管理员强制解绑设备")
    public BaseResponse unbindDevice(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        deviceService.unbindDevice(reqVO.getImei(), language);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_UNBINDING_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 批量导入设备基础详情
     *
     * @param file
     * @param deviceCategoryId
     * @return
     * @throws Exception
     */
    @PostMapping("/importDeviceInfo/{deviceCategoryId}")
    @OperationAnnotation(content = "批量导入设备基础详情")
    public BaseResponse importDeviceInfo(MultipartFile file, @PathVariable("deviceCategoryId") Long deviceCategoryId, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        List<List<Object>> deviceInfos = ExcelUtil.importExcel(file, 0, 0);
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (CollectionUtils.isEmpty(deviceInfos)) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_EXCEL_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(deviceCategoryId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_DEVICE_CATEGORY_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        User user = userClient.selectByPrimaryKey(userId);
        if (null == user.getTenantId() || "".equals(user.getTenantId())) {
            systemParam = systemParamByCacheService.getValues(AuditConstant.AUDIT_ENUM, AuditConstant.AUDIT_NO_COMPANY_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        Tenant tenant = tenantClient.selectByPrimaryKey(user.getTenantId());
        List<CompletableFuture<Device>> collect = deviceInfos.stream().map(device -> CompletableFuture.supplyAsync(() -> parseDevice(device, deviceCategoryId, userId, tenant.getTenantName()), executor)).collect(Collectors.toList());
        List<Device> temp = collect.stream().map(CompletableFuture::join).collect(Collectors.toList());
        List<Device> list = temp.stream().filter(Objects::nonNull).filter(r -> null == r.getAddStatus()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect) || CollectionUtils.isEmpty(temp)) {
            log.info("没有导入的数据");
            return null;
        }
        //不存在的添加
        if (CollectionUtils.isNotEmpty(list)) {
            deviceService.batchInsert(list);
        }
        temp.removeAll(list);
        JSONObject data = new JSONObject();
        data.put("existDevices", temp);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_IMPORT_PREFIX + language);
        return setResultSuccess(systemParam.getMassage(), data);
    }

    /**
     * 导出设备详情数据
     * excel 导出设备详情数据 根据数据库的列信息
     * 在实体类中 - - 去设置实际的值
     * 一定要导出模块 按模块中的数据格式导入数据
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/outDeviceMode", method = RequestMethod.POST)
    @OperationAnnotation(content = "导出设备详情数据")
    public BaseResponse outDeviceMode(@RequestBody DeviceVO reqVO, HttpServletResponse response, HttpServletRequest request) throws Exception {
        List<Device> list = null;
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        DeviceDTO dto = new DeviceDTO();
        if (null != reqVO.getDeviceCategoryId()) {
            dto.setDeviceCategoryId(reqVO.getDeviceCategoryId());
        }
        if (null != reqVO.getProductId()) {
            dto.setProductId(reqVO.getProductId());
        }
        if (null != reqVO.getUsed()) {
            dto.setUsed(reqVO.getUsed());
        }
        dto.setOperatorId(userId);
        dto.setUserId(userId);
        list = deviceService.selectProcessBySelective(dto);
        List<DeviceResVO> resVOS = new ArrayList<>();
        for (Device device : list) {
            DeviceResVO resVO = new DeviceResVO();
            BeanUtils.copyProperties(device, reqVO);
            resVOS.add(resVO);
        }
        String fileName = "Device-" + new Date().getTime() + ".xlsx";
        ExcelUtil.writeExcel(response, fileName, resVOS, DeviceResVO.class);
        return setResultSuccess();
    }

    /**
     * 获取未使用的设备
     * 1. 带卡号，支持模糊搜索
     *
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getUnUsedDevice", method = RequestMethod.POST)
    @OperationAnnotation(content = "获取未使用的设备")
    public BaseResponse getUnUsedDevice(@RequestBody SosVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        /*List<Long> userIds = commonService.getUserIds(userId);
        List<String> imeis = deviceService.getUnUsedImei(userIds, reqVO.getImei(), reqVO.getProductId());*/
        List<Integer> useds = new ArrayList<>();
        useds.add(2);
        useds.add(4);
        DeviceDTO dto = new DeviceDTO();
        if (null != reqVO.getImei()) {
            dto.setImei(reqVO.getImei());
        }
        if (null != reqVO.getProductId()) {
            dto.setProductId(reqVO.getProductId());
        }
        dto.setUserId(userId);
        dto.setOperatorId(userId);
        dto.setUseds(useds);
        List<Device> deviceList = deviceService.selectProcessBySelective(dto);
        List<String> imeis = deviceList.stream().map(Device::getImei).collect(Collectors.toList());
        systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.SELECT_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage(), imeis);
    }

    /**
     * 根据iccid(card_num)同步imei卡号
     *
     * @param reqVO
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/synchronousCardNumber", method = RequestMethod.POST)
    @OperationAnnotation(content = "根据iccid(card_num)同步imei卡号")
    public BaseResponse synchronousCardNumber(@RequestBody SynCardNumberVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getIccid()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ICCID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        iotCardService.updateImeiByIccid(reqVO.getIccid(), reqVO.getImei());
        systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.MODIFY_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * Feign开放接口
     * 根据userId是否存在设备
     *
     * @param userId
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/isHasDeviceByUsers", method = RequestMethod.POST)
    public boolean isHasDeviceByUsers(@RequestBody Long userId) throws Exception {
        boolean flag = false;
        DeviceDTO dto = new DeviceDTO();
        dto.setOperatorId(userId);
        dto.setUserId(userId);
        int count = deviceService.findCountByAll(dto);
        if (count > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * Feign调用接口 根据IMEI查询设备信息
     *
     * @param imei
     * @return
     */
    @PostMapping("/selByImei")
    public Device selByImei(@RequestBody String imei) {
        return deviceService.selByImei(imei);
    }

    /**
     * 设备多选绑定围栏
     *
     * @param reqVO
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/deviceBindFence", method = RequestMethod.POST)
    @OperationAnnotation(content = "设备多选绑定围栏")
    public BaseResponse deviceBindFence(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(userId).isPresent()) {
            systemParam = systemParamByCacheService.getValues(RedisConstant.REDIS_ENUM, RedisConstant.TOKEN_CACHE_EXCEPTION_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (CollectionUtils.isEmpty(reqVO.getIds())) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (CollectionUtils.isEmpty(reqVO.getImeis())) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (reqVO.getFenceId().equals(null) && "".equals(reqVO.getFenceId())) {
            systemParam = systemParamByCacheService.getValues(FenceConstant.FENCE_ENUM, FenceConstant.FENCE_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        List<CompletableFuture<FenceDevice>> collect = reqVO.getImeis().stream().parallel().map(info -> CompletableFuture.supplyAsync(() ->
                fliterFenceUser(info, reqVO.getFenceId()))).collect(Collectors.toList());
        List<FenceDevice> temp = collect.stream().map(CompletableFuture::join).collect(Collectors.toList());
        List<FenceDevice> fenceDevices = temp.stream().filter(Objects::nonNull).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect) || CollectionUtils.isEmpty(fenceDevices)) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_INFO_UPDATE_SUCCESS_PREFIX + language);
            return setResultSuccess(systemParam.getMassage());
        }
        fenceDeviceService.batchInsert(fenceDevices);
        fenceDevices.stream().parallel().forEach(fenceDevice -> {
            Fence fence = fenceService.selectByPrimaryKey(fenceDevice.getFenceId());
            // 组装json
            JSONObject data = new JSONObject();
            data.put("code", EmqCode.addCriminalFenceCode);
            data.put("askTime", DateUtil.getCurrentTime());
            data.put("fenceDeviceId", fenceDevice.getId());
            data.put("fenceId", fenceDevice.getFenceId());
            data.put("fenceName", fence.getName());
            data.put("fenceType", fence.getFenceType());
            data.put("type", fence.getType());
            data.put("imei", fenceDevice.getImei());
            data.put("lat", fence.getLat());
            data.put("lon", fence.getLon());
            data.put("radius", fence.getRadius());
            data.put("userId", fence.getUserId());
            // 主键id-->只有这条是接收topic需要用到的

            // 推送绑定围栏topic给设备
            publishService.sendToMqtt(data.toJSONString(), EmqCode.sendTopic + fenceDevice.getImei() + EmqCode.endTopic);
        });
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_INFO_UPDATE_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    public FenceDevice fliterFenceUser(String imei, Long fenceId) {
        FenceDevice fd = new FenceDevice();
        fd.setImei(imei);
        fd.setFenceId(fenceId);
        int count = fenceDeviceService.findCountByAll(fd);
        if (count > 0) {
            return null;
        }
        fd.setSetStatus(1);
        fd.setCreateTime(new Date());
        fd.setState(1);
        return fd;
    }

    /**
     * @param exp
     * @param deviceCategoryId
     * @param userId
     * @return
     */
    private Device parseDevice(List<Object> exp, Long deviceCategoryId, Long userId, String tenantName) {
        Device device = new Device();
        //device表插入productid
        DeviceCategory deviceCategory = deviceCategoryService.selectByPrimaryKey(deviceCategoryId);
        if (null != deviceCategory) {
            device.setProductId(deviceCategory.getProductId());
        }
        device.setDeviceCategoryId(deviceCategoryId);
        device.setUserId(userId);
        device.setUsed(1);
        device.setState(2);
        device.setCompany(tenantName);
        device.setCreateTime(new Date());
        device.setUpdateTime(new Date());
        if (null == exp.get(1) || null == exp.get(3) || null == exp.get(4) || null == exp.get(6) || null == exp.get(7)) {
            return null;
        }
        if (null == exp.get(0)) {
            device.setName(deviceCategory.getName());
        } else {
            device.setName(String.valueOf(exp.get(0)));
        }

        device.setImei(String.valueOf(exp.get(1)));
        if (null != String.valueOf(exp.get(2))) {
            device.setIccid(String.valueOf(exp.get(2)));
        }
        device.setImsi(String.valueOf(exp.get(3)));
        device.setOperator(String.valueOf(exp.get(4)));
        device.setSku(String.valueOf(exp.get(5)));
        device.setSysVersion(String.valueOf(exp.get(6)));
        device.setAppVersion(String.valueOf(exp.get(7)));

        DeviceDTO query = new DeviceDTO();
        query.setImei(device.getImei());
        int count = deviceService.findCountByAll(query);
        if (count > 0) {
            device.setAddStatus(0); //用来判断设备是否存在的
            return device;
        }
        return device;
    }

    private Device parseDeviceTest(List<Object> exp, Long deviceCategoryId, Long userId) {
        Device device = new Device();
        //device表插入productid
        DeviceCategory deviceCategory = deviceCategoryService.selectByPrimaryKey(Long.valueOf(String.valueOf(exp.get(8))));
        if (null != deviceCategory) {
            device.setProductId(deviceCategory.getProductId());
        }
        device.setDeviceCategoryId(Long.valueOf(String.valueOf(exp.get(8))));
        device.setUserId(1L);
        device.setUsed(1);
        device.setState(2);
        device.setCreateTime(new Date());
        device.setUpdateTime(new Date());
        if (null == exp.get(0) || null == exp.get(1) || null == exp.get(3) || null == exp.get(4) || null == exp.get(6) || null == exp.get(7)) {
            return null;
        }
        device.setName(String.valueOf(exp.get(0)));
        device.setImei(String.valueOf(exp.get(1)));
        if (null != String.valueOf(exp.get(2))) {
            device.setIccid(String.valueOf(exp.get(2)));
        }
        device.setImsi(String.valueOf(exp.get(3)));
        device.setOperator(String.valueOf(exp.get(4)));
        device.setSku(String.valueOf(exp.get(5)));
        device.setSysVersion(String.valueOf(exp.get(6)));
        device.setAppVersion(String.valueOf(exp.get(7)));

        DeviceDTO query = new DeviceDTO();
        query.setImei(device.getImei());
        int count = deviceService.findCountByAll(query);
        if (count > 0) {
            device.setAddStatus(0); //用来判断设备是否存在的
            return device;
        }
        return device;
    }


    /**
     * 获取拍照上传图片信息
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getPhotoUpload", method = RequestMethod.POST)
    @OperationAnnotation(content = "获取拍照上传图片信息")
    public BaseResponse getPhotoUpload(@RequestBody VersionVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        List<PhotoUpload> photoUploads = photoUploadService.selectByImei(reqVO.getImei());
        return setResultSuccess(photoUploads);
    }


    /**
     * 设备列表中充值接口，根据NB和非NB设备查询套餐
     *
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getIotProductList", method = RequestMethod.POST)
    @OperationAnnotation(content = "设备列表中充值接口，根据NB和非NB设备查询套餐")
    public BaseResponse getIotProductList(@RequestBody IotProductVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(reqVO.getImei()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getProductType()).isPresent()) {
            systemParam = systemParamByCacheService.getValues(IotProductConstant.IOTPRODUCT_ENUM, IotProductConstant.IOTPRODUCT_MUST_TYPE_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        Device device = deviceService.selByImei(reqVO.getImei());

        IotProductReq iotProductReq = new IotProductReq();
        iotProductReq.setProductType(reqVO.getProductType());
        if (StringUtils.isNotEmpty(device.getNbDeviceId())) {
            iotProductReq.setCardType(1);
        } else {
            iotProductReq.setCardType(2);
        }
        //TODO 需要改造，现在没空
        ClientResult<List<IotProductRes>> iotProducts = iotcardOrderClient.getProductList(iotProductReq);
        Map<String, Object> msg = new HashMap<>();
        msg.put("iotProducts", iotProducts);
        return setResultSuccess(msg);
    }

    /**
     * 更新室内地图
     *
     * @param reqVO
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateIndoorImg", method = RequestMethod.POST)
    @OperationAnnotation(content = "更新室内地图")
    public BaseResponse updateIndoorImg(@RequestBody DeviceVO reqVO, HttpServletRequest request) throws Exception {
        SystemParam systemParam = null;
        String secretKey = commonService.getWebSalt(request);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        if (CollectionUtils.isEmpty(reqVO.getImeis())) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            return setResultError(systemParam.getCode(), systemParam.getMassage());
        }
        if (StringUtils.isEmpty(reqVO.getIndoorImg())) {
            systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMGURL_PREFIX + language);
            return setResultError(systemParam.getCode(), systemParam.getMassage());
        }

        Set<String> imeis = new HashSet<String>();
        imeis.addAll(reqVO.getImeis());
        List<Device> deviceList = deviceService.selectByimeis(imeis);
        if (CollectionUtils.isEmpty(deviceList)) {
            systemParam = systemParamByCacheService.getValues(SystemParamConstant.SYSTEM_PARAM_ENUM, SystemParamConstant.SYSTEMPARAM_NO_DATA_PREFIX + language);
            return setResultError(systemParam.getCode(), systemParam.getMassage());
        }

        deviceList.stream().forEach(
                device -> {
                    device.setUpdatedBy(userName);
                    device.setIndoorImg(reqVO.getIndoorImg());
                    device.setUpdateTime(new Date());
                }
        );
        deviceService.updateBatchSelective(deviceList);
        systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_UPDATE_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

}
